<template>
  <div class="task-listener">
    <div class="listener-header">
      <span>任务监听器列表</span>
      <a-button type="primary" size="small" @click="handleAddListener">
        <template #icon><plus-outlined /></template>
        添加
      </a-button>
    </div>
    <a-table
      :columns="columns"
      :data-source="tableData"
      :pagination="false"
      size="small"
    >
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'action'">
          <a-space>
            <a-button type="link" size="small" @click="handleEditListener(record)">编辑</a-button>
            <a-button type="link" size="small" danger @click="handleDeleteListener(record)">删除</a-button>
          </a-space>
        </template>
      </template>
    </a-table>

    <a-modal
      v-model:open="editPanelVisible"
      title="编辑任务监听器"
      :confirm-loading="loading"
      @ok="handleConfirm"
      @cancel="handleCancel"
    >
      <task-listener-form
        ref="formRef"
        v-model:listener="listenerObject"
      />
    </a-modal>
  </div>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import { PlusOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { useBpmnModeler, useBpmnSelectedElem } from '/@/config/app.hooks'
import emitter from '/@/event/mitt'
import TaskListenerForm from './TaskListenerForm.vue'
import { BpmnUtil } from "/@/components/bpmn/form/util"

const bpmnModeler = useBpmnModeler()
const bpmnSelectedElem = useBpmnSelectedElem()

const loading = ref(false)
const formRef = ref()
const tableData = computed(() => {
  const selectedElem = bpmnSelectedElem.value
  if (!selectedElem) {
    return []
  }

  const bo = selectedElem.businessObject
  const extensionElements = bo.get('extensionElements')
  if (extensionElements) {
    const values = extensionElements.values
    console.log(values)
    const tmep = values
      .filter(v => v.$type === 'flowable:TaskListener')
      .map(v => ({
        id: v.id,
        event: v.event,
        type: v.class ? 'class' : v.expression ? 'expression' : 'delegateExpression',
        value: v.class || v.expression || v.delegateExpression
      }))
    console.log(tmep)
    return tmep
  } else {
    return []
  }
})

const originalListenerObject = ref()
const listenerObject = ref()
const editPanelVisible = ref(false)

const columns = [
  {
    title: '事件类型',
    dataIndex: 'event',
    key: 'event',
    width: 100
  },
  {
    title: '监听器类型',
    dataIndex: 'type',
    key: 'type',
    width: 120
  },
  {
    title: '值',
    dataIndex: 'value',
    key: 'value',
    ellipsis: true
  },
  {
    title: '操作',
    key: 'action',
    width: 120,
    fixed: 'right'
  }
]

function handleEditListener(listener) {
  listenerObject.value = listener
  originalListenerObject.value = JSON.parse(JSON.stringify(listener))
  editPanelVisible.value = true
}

function handleAddListener() {
  listenerObject.value = {
    event: 'create',
    type: 'class',
    value: '',
  }
  originalListenerObject.value = undefined
  editPanelVisible.value = true
}

const bpmnUtil = new BpmnUtil(bpmnModeler)
async function handleConfirm() {
  // loading.value = true
  try {
    await formRef.value.validate()
  } catch (error) {
    const errorMessages = error?.errorFields?.map((it, idx) => 
      `<div style="margin-bottom: ${idx === error.errorFields.length - 1 ? '0' : '4'}px">${it.errors[0]}</div>`
    ).join('') || '表单验证失败'
    
    message.error({
      dangerouslyUseHTMLString: true,
      duration: 6000,
      content: errorMessages,
    })
    console.error('表单验证错误:', error)
    // loading.value = false
    return
  }

  if (!listenerObject.value) {
    return
  }

  const type = listenerObject.value.type
  if (type !== 'class') {
    listenerObject.value.fields = []
  } else {
    const names = new Set(listenerObject.value.fields?.map(it => it.name) || [])
    if (listenerObject.value.fields && names.size !== listenerObject.value.fields.length) {
      message.error('字段名不允许重复')
      return
    }

    if (listenerObject.value.fields?.some(it => !it?.name?.trim())) {
      message.error('请先填写字段名')
      return
    }

    if (listenerObject.value.fields?.some(it => !it?.value?.trim())) {
      message.error('请先填写字段值')
      return
    }
  }
  if (type === 'delegateExpression') {
    message.error('禁止使用delegateExpression')
    return
  }
  if (bpmnSelectedElem.value.type === 'bpmn:SequenceFlow') {
    listenerObject.value.event = undefined
  }

  console.log('处理后的监听器结构', listenerObject.value)
  console.log('tableData', tableData.value)
  const bo = bpmnSelectedElem.value.businessObject
  let extensionElements = bo.get('extensionElements')
  if (!extensionElements) {
    extensionElements = bpmnModeler.value.get('moddle').create('bpmn:ExtensionElements', { values: []})
  }
  const values = extensionElements.values

  let fields = undefined
  if (listenerObject.value?.fields?.length) {
    fields = []
    for (const field of listenerObject.value?.fields) {
      const bpmnField = bpmnModeler.value.get('moddle').create('flowable:Field', {
        name: field.name,
        [field.type]: field.value
      })
      fields.push(bpmnField)
    }
  }

  const executionListener = bpmnModeler.value.get('moddle').create('flowable:TaskListener', {
    event: listenerObject.value.event,
    [listenerObject.value.type]: listenerObject.value.value,
    fields,
  })

  if (originalListenerObject.value) {
    const originalObj = originalListenerObject.value
    const index = values.findIndex(it => it.$type === 'flowable:TaskListener' && it.event === originalObj.event && it[originalObj.type] === originalObj.value)
    if (index === -1) {
      throw new Error("找不到源监听器对象")
    }
    values[index] = executionListener
  } else {
    values.push(executionListener)
    bpmnUtil.updateProperty(bpmnSelectedElem, {
      extensionElements
    })
  }

  bpmnUtil.updateModelingProperty(bpmnSelectedElem, extensionElements, { values })

  editPanelVisible.value = false
}

function handleCancel() {
  tableData?.effect?.scheduler?.()
  editPanelVisible.value = false
}

function handleDeleteListener(listener) {
  const bo = bpmnSelectedElem.value.businessObject
  const extensionElements = bo.get('extensionElements')
  if (extensionElements) {
    extensionElements.values = extensionElements.values.filter(v => v.id !== listener.id)
    bpmnUtil.updateProperty(bpmnSelectedElem, {
      extensionElements
    })
    tableData?.effect?.scheduler?.()
  }
}

function handleElementChanged(event) {
  tableData?.effect?.scheduler?.()
}

function handleSelectionChanged(event) {
  editPanelVisible.value = false
}

emitter.on('bpmnElementChanged', handleElementChanged)
emitter.off('bpmnElementChanged', handleElementChanged)

emitter.on('bpmnSelectionChanged', handleSelectionChanged)
emitter.off('bpmnSelectionChanged', handleSelectionChanged)
</script>

<style scoped>
.task-listener {
  padding: 12px;
}

.listener-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}
</style>
